// Win32PList.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <tlhelp32.h>
#include <Psapi.h>

void printError( TCHAR* msg )
{
    DWORD eNum;
    TCHAR sysMsg[256];
    TCHAR* p;

    eNum = GetLastError( );
    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, eNum,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
        sysMsg, 256, NULL );

    // Trim the end of the line and terminate it with a null
    p = sysMsg;
    while( ( *p > 31 ) || ( *p == 9 ) )
        ++p;
    do { *p-- = 0; } while( ( p >= sysMsg ) &&
        ( ( *p == '.' ) || ( *p < 33 ) ) );

    // Display the message
    _tprintf( TEXT("\n  WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
}

BOOL ListProcessModules( DWORD dwPID )
{
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    MODULEENTRY32 me32;

    // Take a snapshot of all modules in the specified process.
    hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
    if( hModuleSnap == INVALID_HANDLE_VALUE )
    {
        printError( TEXT("CreateToolhelp32Snapshot (of modules)") );
        return( FALSE );
    }

    // Set the size of the structure before using it.
    me32.dwSize = sizeof( MODULEENTRY32 );

    // Retrieve information about the first module,
    // and exit if unsuccessful
    if( !Module32First( hModuleSnap, &me32 ) )
    {
        printError( TEXT("Module32First") );  // show cause of failure
        CloseHandle( hModuleSnap );           // clean the snapshot object
        return( FALSE );
    }

    // Showing full path of process
    _tprintf( TEXT("\nPROCESS PATH:  %s"), me32.szExePath );  

    // Now walk the module list of the process,
    // and display information about each module

    _tprintf( TEXT("\nMODULES: \n") );
    
    do
    {
        _tprintf( TEXT("\t%s\n"),   me32.szModule );
    } while( Module32Next( hModuleSnap, &me32 ) );

    CloseHandle( hModuleSnap );
    return( TRUE );
}

void PrintMemoryInfo( DWORD dwPID )
{
    HANDLE hProcess;
    PROCESS_MEMORY_COUNTERS_EX pmc;

    // Print information about the memory usage of the process.
    hProcess = OpenProcess(  PROCESS_QUERY_INFORMATION |
        PROCESS_VM_READ,
        FALSE, dwPID );
    if (NULL == hProcess)
        return;

    // Showing memory information
    _tprintf( TEXT("\nMEMORY INFO:  \n"));  

    if ( GetProcessMemoryInfo( hProcess, (PROCESS_MEMORY_COUNTERS *) &pmc, sizeof(pmc)) )
    {
        printf( "\tWorking Set Size: \t%u\n", pmc.WorkingSetSize );
        printf( "\tPeak Working Set Size: \t%u\n", pmc.PeakWorkingSetSize );
        printf( "\tPagefile Bytes: \t%u\n", pmc.PagefileUsage );
        printf( "\tPeak Pagefile Bytes: \t%u\n", pmc.PeakPagefileUsage );
    }

    CloseHandle( hProcess );
}

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(hSnapshot == INVALID_HANDLE_VALUE)
    {
        printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
        return 1;
    }

    PROCESSENTRY32 pe;
    pe.dwSize = sizeof(PROCESSENTRY32);
    if (!Process32First(hSnapshot, &pe)) 
    {
        printError( TEXT("Process32First") );
        CloseHandle(hSnapshot);
        return 2;
    }

    do
    {
        _tprintf( TEXT("\nPROCESS NAME:  %s"), pe.szExeFile );
        ListProcessModules( pe.th32ProcessID );
        PrintMemoryInfo( pe.th32ProcessID );
        _tprintf( TEXT("\n") );
    } while( Process32Next( hSnapshot, &pe ) );


	return 0;
}